<template>
  <div id="code-editor" ref="codeEditorRef" style="min-height: 400px" />
</template>

<script setup lang="ts">
import * as monaco from "monaco-editor";

import { onMounted, ref, watch, toRaw, withDefaults, defineProps } from "vue";

interface Props {
  value: string;
  language: string;
  handleChange: (v: string) => void;
}

const props = withDefaults(defineProps<Props>(), {
  value: () => "",
  language: () => "java",
  handleChange: (v: string) => {
    console.log("内容变化:", v);
  },
});

const codeEditorRef = ref<HTMLDivElement | null>(null);
const codeEditor = ref<monaco.editor.IStandaloneCodeEditor | null>(null);

onMounted(() => {
  if (!codeEditorRef.value) {
    return;
  }
  // 初始化编辑器时使用初始 language
  codeEditor.value = monaco.editor.create(codeEditorRef.value, {
    value: props.value,
    language: props.language,
    automaticLayout: true,
    colorDecorators: true,
    minimap: { enabled: true },
    readOnly: false,
    theme: "vs-dark",
  });

  codeEditor.value.onDidChangeModelContent(() => {
    props.handleChange(toRaw(codeEditor.value!).getValue());
  });
});

// 防抖：延时更新语言，避免短时间内多次触发更新
let debounceTimer: number | null = null;
watch(
  () => props.language,
  (newLanguage, oldLanguage) => {
    console.log("watch触发：", "旧值=", oldLanguage, "新值=", newLanguage);
    if (newLanguage === oldLanguage) return; // 相同语言不更新

    if (codeEditor.value) {
      const model = codeEditor.value.getModel();
      if (model) {
        if (debounceTimer) {
          clearTimeout(debounceTimer);
        }
        debounceTimer = window.setTimeout(() => {
          console.log("切换语言到:", newLanguage);
          //切换code
          monaco.editor.setModelLanguage(toRaw(model), newLanguage);
        }, 500);
      }
    }
  }
);
//新增监听 props.value，跟随父组件更新代码模板
watch(
  () => props.value,
  (newVal) => {
    console.log("props.value变化：", newVal);
    if (toRaw(codeEditor.value!)) {
      // 防止内容相同触发无限循环
      const currentValue = toRaw(codeEditor.value!).getValue();
      if (currentValue === newVal) return;
      // 或直接使用 setValue（根据是否需要保留撤销历史选择）
      toRaw(codeEditor.value!).setValue(newVal);
    }
  },
  { deep: true }
);
</script>

<style scoped></style>
